//
// Created by 高曦祥 on 2023/11/24.
//
#ifndef TINY_DB_PAGE_POOL_H
#define TINY_DB_PAGE_POOL_H

#include "util/base_types.h"
#include <list>
#include <unordered_map>
#include <memory>
#include <mutex>
#include <atomic>
/**
 * page_pool的初步实现思路:
 * 1. 采用LRU实现对page的替换
 * 2. 采用哈希表，实现对page_id与page的映射
 * 3. put操作时，直接在dbf文件的最后一个页进行追加
 * 4. get操作时，通过page_pos(page_id:offset)实现对相关记录的查找
 * 5. 若get操作时，查无此页，则需从磁盘中加载该page
 * 6. 若put操作时，page_pool已满，则需要根据LRU对最老的page进行唤出
*/

namespace TinyDB {

const t_uint64 g_invalid_page_no = 0XFFFFFFFFFFFFFFFF;
const t_uint64 page_size_default = 16 << 20; // 16M大小

class TFile;
class Page;
class RWLock;

class PagePool {
 public:
  PagePool(TFile* file, t_uint64 page_size, t_uint32 max_page_size);
  ~PagePool();

  void Init(); 
  t_byte* ReadRec(t_uint64 offset, t_uint32 len);
  t_bool WriteRec(t_byte* rec, t_uint32 len);

 private:
  static t_uint32 max_free_page_size_;

  TFile* file_;
  t_uint32 max_page_num_;
  t_uint64 page_size_;
  std::unordered_map<t_uint64, Page*> page_map_;
  std::list<Page*> lru_lst_;
  std::list<Page*> free_lst_;
  t_uint64 last_page_no_;
  std::unique_ptr<RWLock> rw_lock_;
};

class Page {
 public:
 enum PageState {
    INIT_PAGE = 0,    // 正在初始化
    EMPTY_PAGE,       // 空页
    DIRTY_PAGE,       // 脏页 需要刷盘
    CLEAN_PAGE        // 干净的页 无需刷盘
  };

 private:
  t_uint64 page_no_;
  t_uint64 page_len_;
  std::atomic<t_uint32> ref_;       // page的引用计数 为0时方可删除 
  std::atomic<PageState> page_state_;
  std::unique_ptr<t_byte> data_;
  RWLock* rw_lock_;
};

}

#endif //TINY_DB_PAGE_POOL_H
